package com.qixin.activiti.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qixin.activiti.service.IEaEntertainBXNCItfService;
import com.qixin.activiti.utils.EaListenerUtil;
import com.qixin.modules.ea.entity.EaBookDetail;
import com.qixin.modules.ea.entity.EaEntertain;
import com.qixin.modules.ea.service.IEaBookDetailService;
import com.qixin.modules.ea.service.IEaEntertainService;
import com.qixin.modules.log.entity.SysInterfaceLog;
import com.qixin.modules.rzInvoice.service.IEaBillService;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.nc.enums.WSEnum;
import org.jeecg.common.nc.service.NCWebService;
import org.jeecg.common.nc.vo.WSVO;
import org.jeecg.modules.activiti.entity.ActBusiness;
import org.jeecg.modules.activiti.entity.ActZTask;
import org.jeecg.modules.activiti.service.IActZTaskService;
import org.jeecg.modules.nc.service.INcBdPsnjobService;
import org.jeecg.modules.system.service.ISysDictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;

/***
* @Description: 招待费报销推送NC审核通过接口
* @author: CYS
* @date: 2022/3/15 10:58
*/

@Slf4j
@Service
public class EaEntertainBXNCItfServiceImpl implements IEaEntertainBXNCItfService {

    @Autowired
    private IEaEntertainService iEaEntertainService;
    @Autowired
    private IEaBookDetailService eaBookDetailService;
    @Autowired
    private IEaBillService iEaBillService;
    @Autowired
    private IActZTaskService iActZTaskService;
    @Autowired
    private ISysDictService iSysDictService;
    @Autowired
    private INcBdPsnjobService iNcBdPsnjobService;
    @Value(value = "${qixin.ncserver.uri}")
    private  String nCUrl;


    @Override
    public SysInterfaceLog bXApprove(ActBusiness actBusiness, String billNo) throws Exception {
        SysInterfaceLog sysInterfaceLog = new SysInterfaceLog();
        sysInterfaceLog.setBusinessNo(billNo);

            //查询招待报销头
            EaEntertain eaEntertain = iEaEntertainService.getById(actBusiness.getTableId());
            if(null==eaEntertain){
                throw new RuntimeException("根据"+actBusiness.getTableId()+"TableId查询招待报销空！");
            }
            EaListenerUtil.objectDefault(eaEntertain,EaEntertain.class);

            //查询招待报销表体费用明细
            List<EaBookDetail> eaBookDetails = eaBookDetailService.selectByMainId(eaEntertain.getId());
            if(null==eaBookDetails||eaBookDetails.size()==0){
                throw new RuntimeException("根据"+eaEntertain.getId()+"TableId查询招待报销费用明细集合为空！");
            }

            /*
            进入start相关事件调用WSDL在做处理
            */

                JSONObject jsonObject = new JSONObject();
                try {


                    JSONObject jsonHead = new JSONObject();

                    //根据表id查询任务记录最后审批人
                    ActZTask actZTask = iActZTaskService.getActZTaskByTableId(actBusiness.getProcInstId());

                    String userId = null;
                    int i = 0;
                    while (true){
                        i++;
                        userId = iActZTaskService.getActHiIdentitylinkById(actZTask.getProcInstId(), actZTask.getTaskId());

                        if(StrUtil.isNotEmpty(userId) || i==100){
                            break;
                        }
                        Thread.sleep(3000);
                    }
                    if(StrUtil.isEmpty(userId)){
                        throw new RuntimeException("根据表id查询任务记录最后审批人失败！");
                    }

                    /*
                    封装头
                     */
                    //审批人=最后审批人(财务)-用户主键
                    jsonHead.put("approver",actZTask.getOwnerId());
                    //本币汇率=默认为1
                    jsonHead.put("bbhl","1");
                    //报销本币金额=实际付款金额
                    jsonHead.put("bbje",eaEntertain.getActualPayAmt());
                    //币种=人民币-币种主键，直接取人民币主键
                    jsonHead.put("bzbm","1002Z0100000000001K1");
                    jsonHead.put("cjkbbje","0");
                    //冲借款金额=  -金额为0  否
                    jsonHead.put("cjkybje","0");
                    //创建人=创建人-用户主键
                    jsonHead.put("creator",eaEntertain.getCreateBy());
                    jsonHead.put("deptid",eaEntertain.getDeptId());
                    //报销人部门=报销人部门-组织_部门版本信息
                    jsonHead.put("deptid_v",eaEntertain.getDeptId());
                    //单据编号=单据编号
                    jsonHead.put("djbh",eaEntertain.getBillNo());
                    //单据大类=bx-bx
                    jsonHead.put("djdl","bx");
                    //单据类型编码=263X-Cxx-jk-借款单:263X-Cxx-jk
                    jsonHead.put("djlxbm","2645");
                    //单据日期=单据日期-2021-12-15 09:32:43
                    jsonHead.put("djrq", DateUtil.format(eaEntertain.getBillDate(),"yyyy-MM-dd HH:mm:ss") );
                    //单据状态=3-0=暂存，1=保存，2=审核，3=签字，-1=作废，
                    jsonHead.put("djzt",eaEntertain.getState());
                    //原费用承担单位=费用承担单位-组织
                    jsonHead.put("fydwbm",eaEntertain.getCostCompCodeId());
                    //费用承担单位=费用承担单位-组织_版本信息
                    jsonHead.put("fydwbm_v",eaEntertain.getCostCompCodeId());
                    jsonHead.put("dr","0");
                    //报销人单位=报销人单位
                    //原报销人单位=//原报销人单位
                    jsonHead.put("dwbm",eaEntertain.getCompanyCodeId());
                    jsonHead.put("dwbm_v",eaEntertain.getCompanyCodeId());
                    //附件张数=附件张数   否
                    jsonHead.put("fjzs",eaEntertain.getAtNum().equals("")?0:eaEntertain.getAtNum());
                    //原费用承担部门=费用承担部门-组织_部门
                    jsonHead.put("fydeptid",eaEntertain.getCostDept());
                    //费用承担部门=费用承担部门-组织_部门版本信息
                    jsonHead.put("fydeptid_v",eaEntertain.getCostDept());
                    //供应商=供应商-收款对象为供应商，供应商必填  否
                    //供应商=供应商-收款对象为供应商，供应商必填  否
                    jsonHead.put("hbbm",eaEntertain.getRecPersonId());
                    //还款本币金额=  -金额为0
                    jsonHead.put("hkbbje","0");
                    jsonHead.put("hkybje","0");
                    //报销人=报销人
                    jsonHead.put("jkbxr",eaEntertain.getPersonId());
                    //结算方式=支付方式
                    jsonHead.put("jsfs",eaEntertain.getPaymentMethod());
                    //签字日期=最后审核人审核日期
                    jsonHead.put("jsr",actZTask.getOwnerId());
                    //会计年度=单据日期年度
                    jsonHead.put("kjnd","");
                    //会计期间=单据日期月份
                    jsonHead.put("kjqj","");
                    //录入人=录入人-用户主键
                    jsonHead.put("operator",eaEntertain.getCreateBy());
                    //支付状态=3-3=支付完成
                    jsonHead.put("payflag","3");
                    //支付人=最后审批人(财务)
                    jsonHead.put("payman",actZTask.getOwnerId());
                    jsonHead.put("paytarget","0");
                    //pk_billtype=264X-264X
                    jsonHead.put("pk_billtype","264X");
                    //集团=集团
                    jsonHead.put("pk_group","0001A110000000000CLJ");
                    //财务组织=费用承担单位
                    jsonHead.put("pk_fiorg",eaEntertain.getCostCompCodeId());
                    //借款报销单标识 =主表主键
                    jsonHead.put("pk_jkbx","");
                    //原报销单位=费用承担单位
                    jsonHead.put("pk_org",eaEntertain.getCostCompCodeId());
                    //报销单位=费用承担单位
                    jsonHead.put("pk_org_v",eaEntertain.getCostCompCodeId());
                    //原付款单位=费用承担单位
                    jsonHead.put("pk_payorg",eaEntertain.getCostCompCodeId());
                    //付款单位=费用承担单位
                    jsonHead.put("pk_payorg_v",eaEntertain.getCostCompCodeId());
                    //交易类型=NC交易类型主键
                    jsonHead.put("pk_tradetypeid","1001A11000000011GUC5");
                    jsonHead.put("receiver",eaEntertain.getRecPersonId());
                    //审批状态=审批通过-0=审批未通过，1=审批通过，2=审批进行中，3=提交，-1=自由，
                    jsonHead.put("spzt","-1");
                    //生效标志=1-0=未生效，1=已生效，
                    jsonHead.put("sxbz","1");
                    //收支项目=费用项目
                    jsonHead.put("szxmid",eaEntertain.getIndexId());
                    //合计金额=实际付款金额
                    jsonHead.put("total",eaEntertain.getActualPayAmt());
                    //原币金额=实际付款金额
                    jsonHead.put("ybje",eaEntertain.getActualPayAmt());
                    //接待类型
                    jsonHead.put("zyx14",iSysDictService.queryDictTextByKey("reception_type",eaEntertain.getReceptionType()));
                    //支付本币金额 =实际付款金额
                    jsonHead.put("zfbbje",eaEntertain.getActualPayAmt());
                    //支付原币金额 =实际付款金额
                    jsonHead.put("zfybje",eaEntertain.getActualPayAmt());
                    //事由=事由
                    jsonHead.put("zy",eaEntertain.getCause());
                    jsonHead.put("actionCode", "APPROVE" + userId);

                    jsonObject.put("head",jsonHead);
                    /*
                    封装头结束
                     */


                    /*
                    表体封装
                     */
                    JSONArray jsonArrayBody = new JSONArray();
                    for (int a = 0; a < eaBookDetails.size(); a++) {

                        //获取费用明细
                        EaBookDetail eaBookDetail = eaBookDetails.get(a);
                        EaListenerUtil.objectDefault(eaBookDetail, EaBookDetail.class);

                        List<Map<String, Object>> billDetailList=null;

                        try {
                            //获取根据发票id获取发票明细集合
                            billDetailList = iEaBillService.getBillDetailList(eaBookDetail.getFpid());
                        }catch (Exception e){
                            throw new RuntimeException("获取发票明细失败!(StackTrace="+EaListenerUtil.formatStackTrace(e)+")");
                        }

                        //表体封装
                        if (billDetailList!=null||billDetailList.size()>0) {
                            try{
                                JSONArray detaijsonObject = JSON.parseArray(JSON.toJSONString(billDetailList));
                                bodySet(eaEntertain, eaBookDetail, detaijsonObject, jsonArrayBody);
                            }catch (Exception e){
                                throw new RuntimeException("fybx表体封装错误!(StackTrace="+EaListenerUtil.formatStackTrace(e)+")");
                            }
                        } else {
                            throw new RuntimeException("获取发票明细空！");
                        }


                    }

                    jsonObject.put("body", jsonArrayBody);
                    /*
                    表体封装结束
                     */


                    //调用WDSDL
                    WSVO wsvo = NCWebService.sendToWS(nCUrl, WSEnum.SERVEEXPENSEBX, jsonObject.toJSONString());

                    //日志保存
                    if(!wsvo.getStatus()){
                        throw new RuntimeException(wsvo.getMessage());
                    }
                    sysInterfaceLog.setState("1");
                    sysInterfaceLog.setDisposeState("0");
                    sysInterfaceLog.setResult(wsvo.getMessage());
                } catch (Exception e) {
                    sysInterfaceLog.setState("0");
                    sysInterfaceLog.setDisposeState("1");
                    sysInterfaceLog.setResult(e.getMessage());
                }
        sysInterfaceLog.setContent(jsonObject.toJSONString());
        sysInterfaceLog.setCreateTime(new DateTime());
        return sysInterfaceLog;
    }



    /**
     * @Description: 设置表体
     * @author: CYS
     * @date: 2022/2/23 11:12
     * @param eaEntertain:
     * @param eaBookDetail:
     * @param detaijsonArray:
     * @param jsonArrayBody:
     * @Return: com.alibaba.fastjson.JSONObject
     */
    private  void bodySet(EaEntertain eaEntertain, EaBookDetail eaBookDetail, JSONArray detaijsonArray, JSONArray jsonArrayBody)throws Exception{
        for (int a=0;a<detaijsonArray.size();a++) {
            JSONObject jsonBody = new JSONObject();
            //发票明细行税率
            BigDecimal taxRate =detaijsonArray.getJSONObject(a).getBigDecimal("taxRate").divide(new BigDecimal("100"));            //发票明细行实际报销金额
            //发票明细行实际报销金额
            BigDecimal totalAmount=detaijsonArray.getJSONObject(a).getBigDecimal("totalAmount");
            //发票明细行实际报销金额对发票总金额占比
            BigDecimal moneyNProportion=totalAmount.divide(eaBookDetail.getAmount(),2, RoundingMode.HALF_UP);
            //发票实际报销金额
            BigDecimal actualEaAmt=eaBookDetail.getActualEaAmt().multiply(moneyNProportion);
            //税额
            BigDecimal tax = actualEaAmt.divide(taxRate.add(new BigDecimal("1")),2, RoundingMode.HALF_UP).multiply(taxRate);
            //无税金额
            BigDecimal taxless = actualEaAmt.subtract(tax);

            //合计金额=实际报销金额
            jsonBody.put("amount",actualEaAmt);
            //本币金额=实际报销金额
            jsonBody.put("bbje",actualEaAmt);
            //本币余额=  -金额为0  否
            jsonBody.put("bbye", "0");
            //冲借款本币金额=  -金额为0  否
            jsonBody.put("cjkbbje", "0");
            //冲借款原币金额=  -金额为0  否
            jsonBody.put("cjkybje", "0");
            //用餐时间
            jsonBody.put("defitem1",DateUtil.format(eaEntertain.getMealArrangementDate(), "yyyy-MM-dd HH:mm:ss"));
            //发票类型
            jsonBody.put("defitem12", detaijsonArray.getJSONObject(a).getString("fpTypeName"));
            //不含税金额
            jsonBody.put("defitem13", taxless);
            //税率
            jsonBody.put("defitem14", detaijsonArray.getJSONObject(a).getString("taxCode"));
            //税额
            jsonBody.put("defitem15", tax);
            if(eaBookDetail.getFygsr().equals(eaEntertain.getPersonId())){
                //原报销人部门=报销人部门-组织_部门
                jsonBody.put("deptid",eaEntertain.getDeptId());
            }else{
                jsonBody.put("deptid", iNcBdPsnjobService.getById(eaBookDetail.getPsnjobId()).getPkDept());
            }
            //删除标志=0
            jsonBody.put("dr", "0");
            //原报销人单位=//原报销人单位
            jsonBody.put("dwbm",eaEntertain.getCostCompCodeId());
            jsonBody.put("hbbm", eaEntertain.getRecPersonId());
            //还款本币金额=  -金额为0
            jsonBody.put("hkbbje", "0");
            //还款原币金额=  -金额为0
            jsonBody.put("hkybje", "0");
            //报销人=报销人
            jsonBody.put("jkbxr", eaBookDetail.getFygsr());
            //收款对象=收款对象-0=员工，1=供应商，2=客户，
            jsonBody.put("paytarget", "0");
            //报销单业务行标识=子表主键
            jsonBody.put("pk_busitem", "");
            jsonBody.put("pk_jkbx", "");
            //报销类型
            jsonBody.put("pk_reimtype", eaBookDetail.getKind());
            //收款人=收款人-收款对象为员工，收款人必填
            jsonBody.put("receiver",eaEntertain.getRecPersonId());
            //行号=行号-n
            jsonBody.put("rowno",jsonArrayBody.size()+1);
            //收支项目=费用项目
            jsonBody.put("szxmid",eaEntertain.getIndexId());
            //原币金额=实际付款金额
            jsonBody.put("ybje",actualEaAmt);
            //支付本币金额 =实际报销金额
            jsonBody.put("zfbbje",actualEaAmt);
            //支付原币金额 =实际付款金额
            jsonBody.put("zfybje",  actualEaAmt);


            jsonArrayBody.add(jsonBody);
        }

    }



}
